package autorization;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Volk ID = 1001
 * The class is data structure. It contents several tables.
 * In the class read-write synchronisation is realised for several threads
 */
public class ThreadTable<T extends Comparable> {
  //--------------Аттрибуты класса------------------
   private ConcurrentHashMap<T,RecordThreadTable> map; //The hesh-table for data access
  //------------------------------------------------  
   /**
   * Constructor for initialization table attributes
   */
  public ThreadTable() {
     map = new ConcurrentHashMap<T,RecordThreadTable>();
     }

  /**
   * To add a new record into table
   * @param key - the unique key
   * @param record - fields of record
   * @return true - addition was carried out; false - duplicate key
   */
  public boolean addItem(T key, RecordThreadTable record){
    if(map.putIfAbsent(key, record) == null) return true; 
     else return false;  
  }
  
  /**
   * To remove a record
   * @param key - record key
   * @return true - has been remove ;false - key hasn't been found;
   */
  public boolean removeItem(T key){
    if(map.remove(key) == null) return false;
     else return true; 
  }
  /**
   * To get data on a key
   * @param key - record key
   * @return data; if key has been found into table then return null-value
   */
  public RecordThreadTable get(T key){
    return map.get(key);
  }
  /**
   * To remove all record from table
   */
  public void clear(){
    map.clear();
  }
  /**
   * To get records count in table
   * @return количество записей
   */
  public int size(){
   return map.size();            
  }
  /**
   * To rewrite new record value instead of old record value
   * @param key - record key
   * @param newRecord - new record
   * @return true =  overwriting was carred out, false - key hasn't been found
   */
  public boolean set(T key, RecordThreadTable newRecord){
     if(map.replace(key, newRecord) == null) return false; 
      else return true; 
  }  
  
  /**
   * To check up presentce of the set key in the table
   * @param key - record key
   * @return true - key is presentces in the table, false - key isn't presentces in
   * the table
   */
  public boolean isKey(T key){
    return map.containsKey(key);
  }
  
  /**
   * To get iterator
   * @return new iterator
   */
  public ThreadTableIterator getIterator(){
    return new ThreadTableIterator();
  }
  
  //--------------The interface methods for operation with the iterator------------------
  /**
   * The class is weekly-iterator. It use for operation with the table
   */
  public class ThreadTableIterator
  { 
    private Iterator iteratorKey; //hash-table iterator
    private T key = null; //current login
    private RecordThreadTable record = null; //Current record
    /**
     *Constructor. To set the cursor on the collection begin
     */
    public ThreadTableIterator(){
     begin(); 
    }
    
    /**
     * To set the iterator on the collection begin
     */
    public void begin(){
     iteratorKey = map.keySet().iterator();     
    }
    
    /**
     * To check up next collection element
     * @return true - the element is exits, false - the element isn't exist
     */
    public boolean hasNext(){
     if(iteratorKey.hasNext()) return true; 
      else return false; 
    }
    
    /**
     * To pass to a next element
     * @return true - transition has carred out , false - transition hasn't carred out
     */
    public boolean Next(){
     record = null; 
     key = null;
     if(hasNext()){ 
     key = (T)iteratorKey.next();    
     record = map.get(key); 
     //to provide spatial synchronisation a next method is entered:
     //in a case if the key has been removed after its reception we consider, that
     //and was at the moment of a call of function and the repeated call is carried out,
     //thus we exclude possibility generation by function "Next"
     //incorrect (from the point of view of processing) values.
     if(record == null) return Next();
     return true; 
     }else return false;
    }
    
    /**
     * To get current record. If current record is not set, then return null-value
     * @return current record
     */
    public RecordThreadTable getRecord(){
     return record; 
    }
    
    /**
     * To get current key. If current key is not set, then return null-value
     * @return current key
     */
    public T getKey(){ 
     return key; 
    }
  }
     
  //-----------------------------------------------------------------------
}

